#include <sys/types.h>
#include <sys/stat.h>
#include <rclcpp/rclcpp.hpp>
#include <dirent.h>
#include <string>
#include <memory>

#include "agv_srvs/srv/file_transform.hpp"

using namespace std;
using std::placeholders::_1;
using std::placeholders::_2;

class AgvParamTransformNode : public rclcpp::Node
{
public:
    AgvParamTransformNode() : Node("agv_param_transform")
    {
        // 获取home目录路径
        string home_path = getenv("HOME");
        
        // 声明并获取参数
        this->declare_parameter<string>("logfile_path", "/logs");
        this->declare_parameter<string>("params_path", "/params");
        
        string log_path = this->get_parameter("logfile_path").as_string();
        string params_path = this->get_parameter("params_path").as_string();
        
        logpath_ = home_path + log_path;
        parampath_ = home_path + params_path;
        obstaclefilepath_ = home_path + params_path;
        
        RCLCPP_INFO(this->get_logger(), "log_file: %s", logpath_.c_str());
        RCLCPP_INFO(this->get_logger(), "param_file: %s", parampath_.c_str());
        RCLCPP_INFO(this->get_logger(), "obsta_file: %s", obstaclefilepath_.c_str());

        // 创建服务
        service_ = this->create_service<agv_srvs::srv::FileTransform>(
            "param_config",
            std::bind(&AgvParamTransformNode::file_config_callback, this, _1, _2));
            
        RCLCPP_INFO(this->get_logger(), "param_config service is start....");
    }

private:
    void file_config_callback(
        const std::shared_ptr<agv_srvs::srv::FileTransform::Request> request,
        std::shared_ptr<agv_srvs::srv::FileTransform::Response> response)
    {
        const char* log_path = logpath_.c_str();
        const char* param_path = parampath_.c_str();
        const char* obstacle_path = obstaclefilepath_.c_str();

        DIR* d = NULL;
        struct dirent* file;
        struct stat st;

        RCLCPP_INFO(this->get_logger(), "Request file name: %s", request->file_name.c_str());

        if(request->file_name.find("Param") != string::npos) {
            if(!(d = opendir(param_path))){
                RCLCPP_ERROR(this->get_logger(), "路径%s打开错误", param_path);
                response->status = 0;
                return;
            };
            RCLCPP_INFO(this->get_logger(), "路径%s打开", param_path);

            while((file = readdir(d)) != NULL) {
                if(strncmp(file->d_name, ".", 1) == 0)
                    continue;
                    
                RCLCPP_INFO(this->get_logger(), "开始读取文件%s", file->d_name);

                if(file->d_type == DT_REG && string(file->d_name) == request->file_name) {
                    RCLCPP_INFO(this->get_logger(), "文件名：%s", file->d_name);
                    string stat_filename = parampath_ + "/" + request->file_name;
                    int status = stat(stat_filename.c_str(), &st);
                    RCLCPP_INFO(this->get_logger(), "stat状态:%d", status);
                    RCLCPP_INFO(this->get_logger(), "接收文件大小:%ld", request->recfilesize);
                    
                    if(status == 0 && request->recfilesize == st.st_size) {
                        response->sendfilesize = st.st_size;
                        response->status = 1;
                        break;
                    } else if(status == 0 && request->recfilesize != st.st_size) {
                        response->sendfilesize = st.st_size;
                        response->status = 0;
                        break;
                    } else {
                        RCLCPP_ERROR(this->get_logger(), "文件打开错误");
                        response->status = 0;
                    }
                }
            }
            RCLCPP_INFO(this->get_logger(), "参数文件传输状态:%d", response->status);
        } 
        else if (request->file_name.find("Obstacle") != string::npos) {
            if(!(d = opendir(obstacle_path))){
                RCLCPP_ERROR(this->get_logger(), "路径%s打开错误", obstacle_path);
                response->status = 0;
                return;
            };
            RCLCPP_INFO(this->get_logger(), "路径%s打开", obstacle_path);

            while((file = readdir(d)) != NULL) {
                if(strncmp(file->d_name, ".", 1) == 0)
                    continue;
                    
                RCLCPP_INFO(this->get_logger(), "开始读取文件%s", file->d_name);

                if(file->d_type == DT_REG && string(file->d_name) == request->file_name) {
                    RCLCPP_INFO(this->get_logger(), "文件名：%s", file->d_name);
                    string stat_filename = obstaclefilepath_ + "/" + request->file_name;
                    int status = stat(stat_filename.c_str(), &st);
                    RCLCPP_INFO(this->get_logger(), "stat状态:%d", status);
                    RCLCPP_INFO(this->get_logger(), "接收文件大小:%ld", request->recfilesize);
                    
                    if(status == 0 && request->recfilesize == st.st_size) {
                        response->sendfilesize = st.st_size;
                        response->status = 1;
                        break;
                    } else if(status == 0 && request->recfilesize != st.st_size) {
                        response->sendfilesize = st.st_size;
                        response->status = 0;
                        break;
                    } else {
                        RCLCPP_ERROR(this->get_logger(), "文件打开错误");
                        response->status = 0;
                    }
                }
            }
            RCLCPP_INFO(this->get_logger(), "障碍物文件传输状态:%d", response->status);
        } 
        else {
            if(!(d = opendir(log_path))){
                RCLCPP_ERROR(this->get_logger(), "路径%s打开错误", log_path);
                response->status = 0;
                return;
            };
            RCLCPP_INFO(this->get_logger(), "路径%s打开", log_path);

            while((file = readdir(d)) != NULL) {
                if(strncmp(file->d_name, ".", 1) == 0)
                    continue;
                    
                RCLCPP_INFO(this->get_logger(), "开始读取文件%s", file->d_name);

                if(file->d_type == DT_REG && string(file->d_name) == request->file_name) {
                    RCLCPP_INFO(this->get_logger(), "文件名：%s", file->d_name);
                    string stat_filename = logpath_ + "/" + request->file_name;
                    int status = stat(stat_filename.c_str(), &st);
                    RCLCPP_INFO(this->get_logger(), "stat状态:%d", status);
                    RCLCPP_INFO(this->get_logger(), "接收文件大小:%ld", request->recfilesize);
                    
                    if(status == 0 && request->recfilesize == st.st_size) {
                        response->sendfilesize = st.st_size;
                        response->status = 1;
                        break;
                    } else if(status == 0 && request->recfilesize != st.st_size) {
                        response->sendfilesize = st.st_size;
                        response->status = 0;
                        break;
                    } else {
                        RCLCPP_ERROR(this->get_logger(), "文件打开错误");
                        response->status = 0;
                    }
                }
            }
            RCLCPP_INFO(this->get_logger(), "日志文件传输状态:%d", response->status);
        }
        
        if(d && closedir(d) != 0) {
            RCLCPP_ERROR(this->get_logger(), "DIR closed failed");
        }
    }
    
    rclcpp::Service<agv_srvs::srv::FileTransform>::SharedPtr service_;
    std::string logpath_;
    std::string parampath_;
    std::string obstaclefilepath_;
};

int main(int argc, char *argv[]){
    setlocale(LC_ALL,"");
    rclcpp::init(argc, argv);
    auto node = std::make_shared<AgvParamTransformNode>();
    rclcpp::spin(node);
    rclcpp::shutdown();
    return 0;
}